package de.rj.urwalking.data;

import java.util.HashMap;

import android.content.Context;
import android.graphics.Bitmap;

import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
import com.threed.jpct.TextureManager;
import com.threed.jpct.util.BitmapHelper;

import de.rj.urwalking.R;
import de.rj.urwalking.ui.OutdoorRenderer;

/**
 * 
 * A subclass of {@link SalientObject} that represents a point of interest from OSM.
 * 
 * @author rjj
 * 
 */

public class Poi extends SalientObject {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private double x;
	private double y;
	private int osmId;
	private HashMap<String, String> tags = new HashMap<String, String>();
	private boolean hasMeaningfulIcon;

	// convert tags to ids to be able to switch
	private enum TextureName {
		bakery, bank, bench, bicycle_parking, bus_stop, cafe, emergency_phone, entrance, fast_food, firestation, fuel, parking, parking_space, pharmacy, place_of_worship, post_box, power_tower, recycling, restaurant, school, supermarket, telephone, traffic_signals, vending_machine, waste_basket, shop, elevator, escalator, stairs, entry, NOVALUE;

		public static TextureName toId(String str) {
			try {
				return valueOf(str);
			} catch (Exception ex) {
				return NOVALUE;
			}
		}
	};

	public Poi(int osmId, double x, double y) {
		// pois are shown in 3D space as a textured plane
		super(Primitives.getPlane(1, 2f));

		this.osmId = osmId;
		this.x = x;
		this.y = y;

		setAdditionalColor(OutdoorRenderer.POI_COLOR);
		setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
		setBillboarding(true);
		strip();
		build();

	}

	public int getOsmId() {
		return osmId;
	}

	public HashMap<String, String> getTags() {
		return tags;
	}

	public double getX() {
		return x;
	}

	public double getY() {
		return y;
	}

	public void setOsmId(int osmId) {
		this.osmId = osmId;
	}

	public void addTag(String tag, String value) {
		tags.put(tag, value);
	}

	public void setX(double x) {
		this.x = x;
	}

	public void setY(double y) {
		this.y = y;
	}

	public void dontShowAsLandmark() {

		clearAdditionalColor();
		setAdditionalColor(OutdoorRenderer.POI_COLOR);
	}

	public boolean hasMeaningfulIcon() {
		return hasMeaningfulIcon;
	}

	/**
	 * 
	 * subtracts an offset from the object coordinates in order to get smaller numbers and increase accuracy.
	 * 
	 * @param offset
	 */
	public void applyOffset(SimpleVector offset) {

		this.x -= offset.x;
		this.y -= offset.y;

		translate((float) x, (float) y, 2f);

	}

	/**
	 * 
	 * loads and sets an icon as texture for the poi plane
	 * 
	 * @param context
	 */

	public void setIcon(Context context) {

		String textureName = determineIcon();

		TextureManager tm = TextureManager.getInstance();
		// Check if we are already using this icon for another poi. In this
		// case, we don't have to load it.
		if (!tm.containsTexture(textureName)) {
			Bitmap icon = BitmapHelper.rescale(
					BitmapHelper.convert(context.getResources().getDrawable(findDrawableForName(textureName))), 64, 64);
			Texture texture = new Texture(icon, true);
			
			// check again
			if (!tm.containsTexture(textureName)) {
				tm.addTexture(textureName, texture);
			}
		}

		setTexture(textureName);

	}

	/**
	 * Checks some common tags/values that we have icons prepared for
	 * 
	 * @return a String containing the name of the texture
	 */

	private String determineIcon() {

		hasMeaningfulIcon = true;

		// do we have a value for tag "amenity"?
		if (tags.get("amenity") != null) {

			// is this value in our controlled set, i.e. do we have a icon
			// prepared for it?
			for (TextureName texName : TextureName.values()) {
				if (tags.get("amenity").equals(texName.name())) {
					return tags.get("amenity");
				}
			}

		}
		// do we have a value for tag "name"?
		if (tags.get("name") != null) {
			String name = tags.get("name");

			// some common "name" values
			if (name.contains("Packstation")) {
				return "post_box";
			}
			if (name.equals("Netto") || name.equals("ALDI") || name.equals("Norma") || name.equals("Edeka")
					|| name.equals("LIDL")) {
				return "supermarket";
			}
			if (name.equals("Sparkasse") || name.equals("Raiffeisenbank")) {
				return "bank";
			}
		}

		// common other values
		if (tags.get("highway") != null) {

			if (tags.get("highway").equals("bus_stop")) {
				return "bus_stop";
			}
			if (tags.get("highway").equals("traffic_signals")) {
				return "traffic_signals";
			}
		}
		if (tags.get("power") != null) {
			if (tags.get("power").equals("tower")) {
				return "power_tower";
			}
		}
		if (tags.get("building") != null) {
			if (tags.get("building").equals("entrance")) {
				return "entrance";
			}
		}
		if (tags.get("barrier") != null) {
			if (tags.get("barrier").equals("entrance")) {
				return "entrance";
			}
		}

		// default texture name. If we didn't find anything appropriate in the
		// tags, we use this one.
		hasMeaningfulIcon = false;
		return "poi";
	}

	private int findDrawableForName(String name) {

		switch (TextureName.toId(name)) {
		case elevator:
			return R.drawable.elevator;
		case stairs:
		case escalator:
			return R.drawable.stairs;
		case bakery:
			return R.drawable.bakery;
		case bank:
			return R.drawable.bank;
		case bench:
			return R.drawable.bench;
		case bicycle_parking:
			return R.drawable.bicycle_parking;
		case bus_stop:
			return R.drawable.bus_stop;
		case cafe:
			return R.drawable.cafe;
		case emergency_phone:
			return R.drawable.emergency_phone;
		case entrance:
		case entry:
			return R.drawable.entrance;
		case fast_food:
			return R.drawable.fast_food;
		case firestation:
			return R.drawable.firestation;
		case fuel:
			return R.drawable.fuel;
		case parking:
		case parking_space:
			return R.drawable.parking;
		case pharmacy:
			return R.drawable.pharmacy;
		case place_of_worship:
			return R.drawable.place_of_worship;
		case post_box:
			return R.drawable.post_box;
		case power_tower:
			return R.drawable.power_tower;
		case recycling:
			return R.drawable.recycling;
		case restaurant:
			return R.drawable.restaurant;
		case school:
			return R.drawable.school;
		case shop:
		case supermarket:
			return R.drawable.supermarket;
		case telephone:
			return R.drawable.telephone;
		case traffic_signals:
			return R.drawable.traffic_signals;
		case vending_machine:
			return R.drawable.vending_machine;
		case waste_basket:
			return R.drawable.waste_basket;
		default:
			return R.drawable.poi;
		}

	}

}
